"""
-------------------------------
- File_Name: system.py
- Date: 2025/3/1
- Author: yangzhide
- Email: xxzjyzd@126.com
- Description: 系统管理相关函数
-------------------------------
"""
from fastapi import HTTPException

from app.models import Role, RoleButton, Button, Menu, RoleMenu, User, UserRole


async def get_user_button(user_obj: User):
    """根据用户对象 返回按钮列表"""

    # 用户所属角色列表
    role_id_list = await UserRole.filter(user_id=user_obj.id).values_list("role_id", flat=True)
    button_id_list = await RoleButton.filter(role_id__in=role_id_list).values_list("button_id", flat=True)
    button_code_list = await Button.filter(id__in=button_id_list).values_list("button_code", flat=True)
    return button_code_list if button_code_list else []


async def build_route_tree(menus: list[Menu], parent_id: int = 0, simple: bool = False) -> list[dict]:
    """
    递归生成路由树
    :param menus:
    :param parent_id:
    :param simple: 是否简化返回数据
    :return:
    """
    tree = []
    for menu in menus:
        # 预加载关联的Role对象
        # await menu.fetch_related('role_menus')
        # menu_roles: list[Role] = menu.role_menus  # type: ignore
        # role_codes = [role.role_code for role in menu_roles]

        if menu.parent_id == parent_id:
            children = await build_route_tree(menus, menu.id, simple)
            if simple:
                menu_dict = {
                    "name": menu.route_name,
                    "path": menu.route_path,
                    "component": menu.component,
                    "meta": {
                        "title": menu.menu_name,
                        "i18nKey": menu.i18n_key,
                        "order": menu.order,
                        "keepAlive": menu.keep_alive,
                        "icon": menu.icon,
                        "iconType": menu.icon_type,
                        "href": menu.href,
                        "activeMenu": menu.active_menu,
                        "multiTab": menu.multi_tab,
                        "fixedIndexInTab": menu.fixed_index_in_tab,
                    }
                }
                if menu.redirect:
                    menu_dict["redirect"] = menu.redirect
                if menu.component:
                    menu_dict["meta"]["layout"] = menu.component.split("$", maxsplit=1)[0]
                if menu.hide_in_menu and not menu.constant:
                    menu_dict["meta"]["hideInMenu"] = menu.hide_in_menu
            else:
                menu_dict = await menu.to_dict()
            if children:
                menu_dict["children"] = children
            tree.append(menu_dict)
    return tree


async def build_menu_tree(menus: list[Menu], parent_id: int = 0, simple: bool = False) -> list[dict]:
    """
    递归生成菜单树
    :param menus:
    :param parent_id:
    :param simple: 是否简化返回数据
    :return:
    """
    tree = []
    # 公共页面禁止选择
    # disable_check = ["首页", "异常页"]
    # p_ids = await Menu.filter(menu_name__in=disable_check).values_list("id", flat=True)
    # all_disable_ids = []
    # for p_id in p_ids:
    #     _id = await get_all_submenu_ids(p_id)
    #     all_disable_ids.extend(_id)

    for menu in menus:
        if menu.parent_id == parent_id:
            children = await build_menu_tree(menus, menu.id, simple)
            if simple:
                menu_buttons_dict = await Button.filter(menu_id=menu.id).values("id", "button_code", "button_desc")
                alias_buttons = []
                if menu_buttons_dict:
                    alias_buttons = [{"bId": button["id"], "code": button["button_code"], "label": button["button_desc"]}
                                     for button in menu_buttons_dict]
                menu_dict = {
                    "id": menu.id,
                    "label": menu.menu_name,
                    "pId": menu.parent_id,
                    "buttons": alias_buttons,
                    # "disabled": False if menu.id not in all_disable_ids else True,
                }
            else:
                menu_dict = await menu.to_dict()
                # 查询与当前菜单关联的按钮对象
                buttons_data = await Button.filter(menu_id=menu_dict["id"]).values("button_code", "button_desc")
                # 为按钮数据设置别名
                buttons_list = [{"code": item["button_code"], "desc": item["button_desc"]} for item in buttons_data]
                menu_dict["buttons"] = buttons_list
            if children:
                menu_dict["children"] = children
            tree.append(menu_dict)
    return tree


async def get_all_submenu_ids(menu_id: int | str):
    """
    递归获取所有子菜单ID（包含自身）
    """
    all_ids = []
    current_ids = [menu_id]
    while current_ids:
        # 将当前menu_id 添加至末尾
        all_ids.extend(current_ids)
        # 查询下一级子菜单
        next_menus = await Menu.filter(parent_id__in=current_ids).all()
        current_ids = [menu.id for menu in next_menus]
    return all_ids


async def delete_menu_and_children(menu_id: int | str):
    """递归删除菜单及其子菜单、按钮和角色菜单数据"""

    # 所有子菜单id(包含自身)
    menu_ids = await get_all_submenu_ids(menu_id)
    # 1. 删除角色菜单表中数据
    await RoleMenu.filter(menu_id__in=menu_ids).delete()
    # 2. 删除菜单按钮
    await Button.filter(menu_id__in=menu_ids).delete()
    # 3. 删除菜单（本身）
    await Menu.filter(id__in=menu_ids).delete()


async def delete_role(role_id: int | str):
    """删除角色菜单及其角色按钮"""
    role_obj = await Role.get_or_none(id=role_id)
    if role_obj is None:
        raise HTTPException(status_code=404, detail=f"删除角色不存在【id={id}】")
    # 1. 删除角色按钮
    await RoleButton.filter(role_id=role_id).delete()
    # 2. 删除用户角色
    await UserRole.filter(role_id=role_id).delete()
    # 3. 删除角色（本身）
    await Role.filter(id=role_id).delete()
